﻿using System;
using System.Collections.Generic;

namespace MathParser.DataModel {

    internal class CalculatorMapper {

        internal delegate double CalcBinär(double value1, double value2);
        internal delegate double CalcUnär(Parser parser, double x);
        internal delegate double CalcConst(double x);

        internal readonly Dictionary<Operation, CalcBinär> BinärMap = new Dictionary<Operation, CalcBinär>();
        internal readonly Dictionary<Operation, CalcUnär> UnärMap = new Dictionary<Operation, CalcUnär>();
        internal readonly Dictionary<Operation, CalcConst> ConstMap = new Dictionary<Operation, CalcConst>();

        internal CalculatorMapper() {

            this.ConstMap.Add(Operation.Variable, x => x);
            this.ConstMap.Add(Operation.Pi, x => Math.PI);
            this.ConstMap.Add(Operation.E, x => Math.E);

            this.BinärMap.Add(Operation.Plus, (x, y) => x + y);
            this.BinärMap.Add(Operation.Minus, (x, y) => x - y);
            this.BinärMap.Add(Operation.Multi, (x, y) => x * y);
            this.BinärMap.Add(Operation.Divi, (x, y) => x / y);
            this.BinärMap.Add(Operation.Potenz, Math.Pow);

            this.UnärMap.Add(Operation.Sinus, (p, x) => Math.Sin(p.ChildLeft.Caluculate(x)));
            this.UnärMap.Add(Operation.Cosinus, (p, x) => Math.Cos(p.ChildLeft.Caluculate(x)));
            this.UnärMap.Add(Operation.Tangens, (p, x) => Math.Tan(p.ChildLeft.Caluculate(x)));
            this.UnärMap.Add(Operation.Sqrt, (p, x) => Math.Sqrt(p.ChildLeft.Caluculate(x)));
            this.UnärMap.Add(Operation.Lg, (p, x) => Math.Log10(p.ChildLeft.Caluculate(x)));
            this.UnärMap.Add(Operation.Ln, (p, x) => Math.Log(p.ChildLeft.Caluculate(x)));
            this.UnärMap.Add(Operation.Lb, (p, x) => Math.Log(p.ChildLeft.Caluculate(x), 2));
            this.UnärMap.Add(Operation.Fakultät, (p, x) => Parser.CalcFakultät(p.ChildLeft.Caluculate(x)));

        }
    }
}